<?php

require_once('php/lib/db/database.php');

/**
 * MySQL database.
 *
 * Configuration settings: 
 *	- config['host'] = hostname
 *	- config['login'] = login
 *	- config['password'] = password
 *  - config['database'] = databasename
 *
 * Optional configuration settings:
 *  - config['persistent'] = indicator (true/false) if persistent connections should be used (defaults to false)
 *
 * @author Pascal de Vink
 */
class MysqlDatabase extends Database {

	/**
	 * Database connection.
	 *
	 * @var handle
	 * @access private
	 */
	var $_connection = NULL;
	
	/**
	 * Database name.
	 *
	 * @var string
	 * @access private
	 */
	var $_database = '';
		
	/** 
	 * Connects to database server.
	 *
	 * @access private
	 */
	function _connect() {
		
		# get connection properties
		$host = $this->config('host', 'host');
		$login = $this->config('login', 'root');
		$password = $this->config('password', '');
		$persistent = $this->config('persistent', false);

		# create connection
		if ($persistent) {
			$this->_connection = @mysql_pconnect($host, $login, $password);
		} else {
			$this->_connection = @mysql_connect($host, $login, $password);
		}
		
		return $this->_connection? true : false;
	}

	/** 
	 * @see Database::open()
	 */
	function open() {
		if ($this->_begin('open', '', false) == false) return false;

		# get database properties
		$database = $this->config('database');

		if (!$database) trigger_error('No database specified');

		# connect if needed
		if (!$this->_connection && !$this->_connect()) {
			return $this->_fail();
		}		
		
		# select database
		if (!mysql_query("USE {$database}", $this->_connection)) {
			return $this->_fail();
		}

		$this->_database = $database;
		return $this->_end();
	}

	/**
	 * @see Database::create()
	 */
	function create() {
		if ($this->_begin('create', '', false) == false) return false;

		# get database properties
		$database = $this->config['database'];
		if (!$database) trigger_error('No database specified');
		
		# connect if needed
		if (!$this->_connection && !$this->_connect()) {
			return $this->_fail();
		}		

		# create database
		$this->_database = $this->config['database'];
		if (!mysql_query("CREATE DATABASE {$database}", $this->_connection)) {
			return $this->_fail();
		}

		# select database
		if (!mysql_query("USE {$database}", $this->_connection)) {
			return $this->_fail();
		}		
		
		$this->_database = $database;
		return $this->_end();
	}
	
	/** 
	 * @see Database::drop()
	 */
	function drop() {
		if ($this->_begin('drop', '', false) == false) return false;

		# get database properties
		$database = $this->config['database'];

		if (!$database) trigger_error('No database specified');
		
		# connect if needed
		if (!$this->_connection && !$this->_connect()) {
			return $this->_fail();
		}		

		# drop database
		if (!mysql_query("DROP DATABASE {$database}", $this->_connection)) {
			return $this->_fail();
		}		
		
		return $this->_end();
	}
	
	/** 
	 * @see Database::close()
	 */
	function close() {
		if ($this->_begin('close', '') == false) return false;

		# close database connection
		if (mysql_close($this->_connection)) {
			$this->_connection = NULL;
			$this->_database = '';
			return $this->_end();
		} else {
			return $this->_fail();
		}
	}

	/**
	 * @see Database::isOpen()
	 */
	function isOpen() {
		return $this->_connection && $this->_database;
	}

	/**
	 * @see Database::query()
	 */
	function &query($query, $limit = NULL, $offset = NULL) {
		if ($this->_begin('query', $query) == false) return false;
		
		# add limit clause
		if (!is_null($limit)) {
			$query .= ' ' . $this->_limitClause($limit, $offset);
		}

		# perform query
		$handle = mysql_query($query, $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}
		
		$this->_end();
		return new MysqlResultSet($this, $handle);		
	}	
	
	
	function &log($end_user_id = 0, $process_name = 'xDSL-order', $message_text, $by='system') {
		
		$now = date("Y-m-d H:i:s");
		
		$query = "	insert into 	process_log
						(			end_user_id
						,			process_name
						,			message_text
						,			created
						,			last_changed_by)
					values(			'$end_user_id'
						,			'$process_name'
						,			'$message_text'
						,			'$now'
						,			'$by')";
		
		# perform query
		$handle = mysql_query($query, $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}
		
		$this->_end();
		return new MysqlResultSet($this, $handle);		
	}	
	
	
	
	/**
	 * @see Database::queryFirst()
	 */
	function &queryFirst($query, $offset = NULL) {
		if ($this->_begin('queryFirst', $query) == false) return false;

		# add limit to query
		$query .= ' ' . $this->_limitClause(1, $offset);

		# perform query
		$handle = mysql_query($query, $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}

		# fetch first record
		$row = mysql_fetch_assoc($handle);
		
		$this->_end();
		return $row;
	}
	
	
	/** 
	 * @see Database::queryAll()
	 */
	function &queryAll($query, $limit = NULL, $offset = NULL) {
		if ($this->_begin('queryAll', $query) == false) return false;

		# add limit to query
		if (!is_null($limit)) {
			$query .= ' ' . $this->_limitClause($limit, $offset);
		}
		
		# perform query
		$handle = mysql_query($query, $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}

		# fetch records
		$rows = array();
		while (($row = mysql_fetch_assoc($handle))) {
			$rows[] = $row;
		}
		
		$this->_end();
		return $rows;
	}
	
	/**
	 * @see Database::execute()
	 */
	function execute($command) {
		if ($this->_begin('execute', $command) == false) return false;
		
		# perform query
		if (!mysql_query($command, $this->_connection)) {
			return $this->_fail();
		}
		
		return $this->_end(mysql_affected_rows($this->_connection));
	}

	/**
	 * @see Database::begin()
	 */
	function begin() {
		if ($this->_begin('begin') == false) return false;
		
		# start transaction
		if (!mysql_query("BEGIN", $this->_connection)) {
			return $this->_fail();
		}
		
		return $this->_end();
	}
	
	/**
	 * @see Database::rollback()
	 */
	function rollback() {
		if ($this->_begin('rollback') == false) return false;
		
		# rollback transaction
		if (!mysql_query("ROLLBACK", $this->_connection)) {
			return $this->_fail();
		}
		
		return $this->_end();
	}
	
	/**
	 * @see Database::commit()
	 */
	function commit() {
		if ($this->_begin('commit') == false) return false;
		
		# commit transaction
		if (!mysql_query("COMMIT", $this->_connection)) {
			return $this->_fail();
		}
		
		return $this->_end();
	}
	
	/** 
	 * @see Database::tables()
	 */
	function tables() {
		if ($this->_begin('tables') == false) return false;

		# retrieve tables
		$handle = mysql_query("SHOW TABLES FROM {$this->_database}", $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}

		# create list of tables
		$tables = array();
		while (($row = @mysql_fetch_array($handle))) {
			$table = array();
			$table['name'] = $row[0];
			$tables[] = $table;
		}
		
		$this->_end();
		return $tables;
	}

	/** 
	 * @see Database::fields()
	 */
	function fields($table_name) {
		if ($this->_begin('fields', "table $table") == false) return false;

		# retrieve table fields
		$handle = mysql_query("SHOW COLUMNS FROM {$table_name} FROM {$this->_database}", $this->_connection);
		if (!$handle) {
			return $this->_fail();
		}

		# create list of fields
		$fields = array();
		while (($row = @mysql_fetch_array($handle))) {
			$fields[] = array('name' => $row[0], 'type' => $row[1], 'null' => $row[2], 'key' => $row[3], 'default' => $row[4]);
		}

		$this->_end();
		return $fields;
	}

	/**
	 * @see Database::lastInsertId()
	 */
	function lastInsertId() {
		return mysql_insert_id($this->_connection);
	}

	/**
	 * @see Database::lastAffected()
	 */
	function lastAffected() {
		return mysql_affected_rows($this->_connection);
	}

	/** 
	 * @see Database::encode()
	 */
	function encode($value) {
		if (is_null($value) || ($this->config('empty_as_null', true) && empty($value)) && !is_numeric($value)) {
			return 'NULL';
		} else if (get_magic_quotes_gpc()) {
	   		return "'" . mysql_real_escape_string(stripslashes($value), $this->_connection) . "'";
   		} else {
	   		return "'" . mysql_real_escape_string($value, $this->_connection) . "'";
   		}
	}

	/**
	 * Returns last occured error
	 *
	 * @return string Last error
	 * @access private
	 */
	function _error() {
		return $this->_connection? mysql_error($this->_connection) : mysql_error();
	}
	
	/**
	 * Returns limit clause for use in an SQL statement.
	 *
	 * @param int $limit Optional limit of results returned
	 * @param int $offset Optional offset from which to start results (starts at 0)
	 * @return string Limit clause
	 * @access private
	 */
	function _limitClause($limit = NULL, $offset = NULL) {
	return (!is_null($limit)? 'LIMIT '.(!is_null($offset)?  $offset.',' : '') . $limit : '');
	}	
}

/** @access private */
class MysqlResultSet extends ResultSet {
	
	/**
	 * Handle for resultset
	 *
	 * @var handle
	 * @access private
	 */
	var $_handle = NULL;
	
	/**
	 * Constructs new instance
	 */
	function __construct(&$database, $handle) {
		parent::__construct($database);
		$this->_handle = $handle;
	}

	/**
	 * @see ResultSet::next()
	 */
	function &next() {
		return mysql_fetch_assoc($this->_handle);
	}
	
	/**
	 * @see ResultSet::resets()
	 */
	function reset() {
		return mysql_data_seek($this->_handle, 0);
	}	

	/**
	 * @see ResultSet::resets()
	 */
	function goto( $ptr = 0) {
		return mysql_data_seek($this->_handle, $ptr);
	}
	
	/**
	 * @see ResultSet::count()
	 */
	function count() {
		return mysql_num_rows($this->_handle);
	}
	
	/**
	 * @see ResultSet::isEmpty()
	 */
	function isEmpty() {
		return mysql_num_rows($this->_handle) == 0;
	}	
	
	/**
	 * @see Database::fields()
	 */
	function fields() {
		$count = mysql_num_fields($this->_handle);
		$fields = array();
		for ($i = 0; $i < $count; $i++) {
			$fields[] = array('name' => mysql_field_name($this->_handle, $i),
					          'type' => mysql_field_type($this->_handle, $i),
						      'length' => mysql_field_len($this->_handle, $i));
		}
		return $fields;
	}

	/**
	 * @see ResultSet::fieldCount()
	 */
	function fieldCount() {
		return mysql_num_fields($this->_handle);
	}
}

# compatibility routines
if(version_compare(phpversion(), "4.3.0") == -1) {
	/** @access private */
	function mysql_real_escape_string($value) {
		return mysql_escape_string($value);
	}
}

if(version_compare(phpversion(), "4.0.3") == -1) {
	/** @access private */
	function mysql_fetch_assoc($value) {
		return mysql_fetch_array($this->_handle, MYSQL_ASSOC);
	}
}
?>